package com.zxl.grocery.core.util;

import com.zxl.grocery.common.exception.BizExceptionEnum;
import com.zxl.grocery.common.exception.BussinessException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.List;

public class FileUtil {
	
	private static Logger log = LoggerFactory.getLogger(FileUtil.class);
	private static final int DEFAULT_BUFFER_SIZE = 1024;

	/**
	 * NIO way
	 */
	public static byte[] toByteArray(String filename) {

		File f = new File(filename);
		if (!f.exists()) {
			log.error("文件未找到！" + filename);
			throw new BussinessException(BizExceptionEnum.FILE_NOT_FOUND);
		}
		FileChannel channel = null;
		FileInputStream fs = null;
		try {
			fs = new FileInputStream(f);
			channel = fs.getChannel();
			ByteBuffer byteBuffer = ByteBuffer.allocate((int) channel.size());
			while ((channel.read(byteBuffer)) > 0) {
				// do nothing
				// System.out.println("reading");
			}
			return byteBuffer.array();
		} catch (IOException e) {
			throw new BussinessException(BizExceptionEnum.FILE_READING_ERROR);
		} finally {
			try {
				channel.close();
			} catch (IOException e) {
				throw new BussinessException(BizExceptionEnum.FILE_READING_ERROR);
			}
			try {
				fs.close();
			} catch (IOException e) {
				throw new BussinessException(BizExceptionEnum.FILE_READING_ERROR);
			}
		}
	}


	/**
	 * 将字符串写入指定文件(当指定的父路径中文件夹不存在时，会最大限度去创建，以保证保存成功！)
	 *
	 * @param res            原字符串
	 * @param filePath 文件路径
	 * @return 成功标记
	 */
	public static boolean string2File(String res, String filePath) {
		boolean flag = true;
		BufferedReader bufferedReader = null;
		BufferedWriter bufferedWriter = null;
		try {
			File distFile = new File(filePath);
			if (!distFile.getParentFile().exists()) distFile.getParentFile().mkdirs();
			bufferedReader = new BufferedReader(new StringReader(res));
			bufferedWriter = new BufferedWriter(new FileWriter(distFile));
			char buf[] = new char[DEFAULT_BUFFER_SIZE];         //字符缓冲区
			int len;
			while ((len = bufferedReader.read(buf)) != -1) {
				bufferedWriter.write(buf, 0, len);
			}
			bufferedWriter.flush();
			bufferedReader.close();
			bufferedWriter.close();
		} catch (IOException e) {
			e.printStackTrace();
			flag = false;
			return flag;
		} finally {
			if (bufferedReader != null) {
				try {
					bufferedReader.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return flag;
	}

	/**
	 * 文本文件转换为指定编码的字符串
	 *
	 * @param file         文本文件
	 * @param encoding 编码类型
	 * @return 转换后的字符串
	 * @throws IOException
	 */
	public static String file2String(File file, String encoding) {
		InputStreamReader reader = null;
		StringWriter writer = new StringWriter();
		String result = "";
		try {
			if (encoding == null || "".equals(encoding.trim())) {
				reader = new InputStreamReader(new FileInputStream(file), encoding);
			} else {
				reader = new InputStreamReader(new FileInputStream(file));
			}
			//将输入流写入输出流
			char[] buffer = new char[DEFAULT_BUFFER_SIZE];
			int n = 0;
			while (-1 != (n = reader.read(buffer))) {
				writer.write(buffer, 0, n);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (reader != null) {
				try {
					reader.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		//返回转换结果
		if (writer != null) {
			result = writer.toString();
			try {
				writer.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return result;
	}

	/**
	 * get all of file name into the list for the given directory.
	 * @param dir, this directory must absolute path.
	 * @param fileNames, uses to contain all of file name
	 */
	public static void getAllFileNames(String dir, List<String> fileNames) {
		if(null==dir || "".equals(dir)) {
			return ;
		}
		File file = new File(dir);
		if(file.isFile()) {
			fileNames.add(file.getPath());
		} else if(file.isDirectory()){
			File[] childFiles = file.listFiles();
			for(File childFile : childFiles) {
				if(childFile.isFile()) {
					fileNames.add(childFile.getPath());
				} else {
					getAllFileNames(childFile.getPath(), fileNames);
				}
			}
		}
	}

	public static void getChildrenDir(String dir, List<String> dirPaths) {
		if(null==dir || "".equals(dir)) {
			return ;
		}
		File file = new File(dir);
		if(file.isDirectory()) {
			File[] children = file.listFiles();
			for(File child : children) {
				if(child.isDirectory()) {
					dirPaths.add(child.getPath());
				}
			}
		}
	}

	public static boolean hasNormalFiles(String dir) {
		if(null==dir || "".equals(dir)) {
			throw new RuntimeException("the directory is null or empty!");
		}
		File file = new File(dir);
		if(file.isDirectory()) {
			File[] children = file.listFiles();
			if(0 == children.length) {
				return false;
			} else {
				return true;
			}
		}
		throw new RuntimeException("the direcotry is not a real directory!");
	}

	/**
	 * delete a normal file
	 * @param filePath
	 */
	public static void delete(String filePath) {
		if(null==filePath || "".equals(filePath)) {
			return ;
		}
		File file = new File(filePath);
		if(file.isFile()) {
			file.delete();
		}
	}

	/**
	 * 将字符串写入指定文件(当指定的父路径中文件夹不存在时，会最大限度去创建，以保证保存成功！)
	 *
	 * @param res 原字符串
	 * @param filePath 文件路径
	 * @return 成功标记
	 */
	public static boolean string2File(String res, String filePath, String encoding) {
		boolean flag = false;
		File distFile = new File(filePath);
		synchronized(FileUtil.class) {
			if (!distFile.getParentFile().exists()) {
				distFile.getParentFile().mkdirs();
			}
		}
		BufferedWriter writer = null;
		try {
			writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(distFile), encoding));
			writer.write(res);
			writer.flush();
			flag = true;
		} catch (IOException e) {
			e.printStackTrace();
			flag = false;
		} finally {
			if(null != writer) {
				try {
					writer.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return flag;
	}

}